package com.haralabidis.jdeveloper.extension.subversionmonitor.addin.editor;


import com.haralabidis.jdeveloper.extension.subversionmonitor.util.xml.XMLExtractor;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import java.net.URL;

import javax.swing.AbstractAction;
import javax.swing.AbstractButton;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

import oracle.javatools.icons.OracleIcons;
import oracle.javatools.ui.ComponentWithTitlebar;
import oracle.javatools.ui.ControlBar;
import oracle.javatools.ui.Header;
import oracle.javatools.ui.HeaderPanel;
import oracle.javatools.ui.ResizeComponent;
import oracle.javatools.ui.TransparentPanel;
import oracle.javatools.ui.layout.VerticalFlowLayout;
import oracle.javatools.ui.plaf.IconicButtonUI;

import oracle.xml.parser.v2.XMLElement;

import org.w3c.dom.NodeList;


final class RevisionsGeneralPane extends TransparentPanel {
    private URL url = null;
    private JTable revisionsTable = null;
    private JTextArea filesChangedField = null;

    RevisionsGeneralPane(URL url) {
        this.url = url;
        layoutComponents();
    }

    private void layoutComponents() {
        setLayout(new VerticalFlowLayout());

        XMLExtractor extractor =
            new XMLExtractor(url.getFile().substring(1), null);
        NodeList rootNodes = extractor.getNodes("SubversionMonitor");
        XMLElement rootNode = ((XMLElement)rootNodes.item(0));


        addPageHeader("Subversion Monitor");

        addSubPanel("Revision Information for " +
                    rootNode.getAttribute("repository"), "List of Revisions",
                    new RevisionsPanel(this.url));
        addSubPanel("Files Changed for Revision",
                    "The files that were changed for this revision",
                    new FilesChangedPanel(this.url));
    }

    private void addSubPanel(String title, String hint, JComponent component) {
        HeaderPanel header_panel = new HeaderPanel();
        header_panel.getHeader().setText(title);
        header_panel.getHeader().setLevel(Header.Level.SUB);
        header_panel.setStaticHelpText(hint);
        header_panel.setHostedComponent(component);

        add(header_panel);
    }

    private void addPageHeader(String pageTitle) {
        Header pageHeader = new Header();
        pageHeader.setText(pageTitle);
        pageHeader.setLevel(Header.Level.PAGE);

        add(pageHeader);
    }

    private static AbstractButton createBrowseButton() {
        JButton b = new JButton();
        IconicButtonUI.install(b);
        b.setIcon(OracleIcons.getIcon(OracleIcons.LOV));

        return b;
    }

    private Action createIconicAction(Icon icon) {
        return new AbstractAction("", icon) {
            public void actionPerformed(ActionEvent e) {
            }
        };
    }

    private class InformationPanel extends TransparentPanel {
        InformationPanel(URL url) {
            //            FieldLayoutBuilder b = new FieldLayoutBuilder(this);
            //            JTextField filename = new JTextField();
            //            filename.setText(url.getFile().substring(1));
            //            b.add(b.field().label(new JLabel()).withText("&Filename:").component(filename));
            //
            //            XMLExtractor xml_extractor =
            //                new XMLExtractor(url.getFile().substring(1));
            //
            //            NodeList root_node = xml_extractor.getNodes("MedNeXtTools");
            //
            //            JTextField run_date = new JTextField();
            //            run_date.setText(((XMLElement)root_node.item(0)).getAttribute("RunDate"));
            //            b.add(b.field().label(new JLabel()).withText("&Run Date:").component(run_date));
            //
            //            JTextField files_verified = new JTextField();
            //            files_verified.setText(((XMLElement)root_node.item(0)).getAttribute("FilesVerified"));
            //            b.add(b.field().label(new JLabel()).withText("&Number of Application Modules:").component(files_verified));
            //            //            b.add(b.field().label(new JLabel()).withText("&Application Modules:").component(new JComboBox()).button(createBrowseButton()).withText(""));
        }
    }

    private class RevisionsPanel extends TransparentPanel {
        RevisionsPanel(URL url) {
            setLayout(new VerticalFlowLayout());

            add(createTable("Revisions", url, true));
        }
    }

    private class FilesChangedPanel extends TransparentPanel {
        FilesChangedPanel(URL url) {
            setLayout(new VerticalFlowLayout());

            filesChangedField = new JTextArea(5, 1);
            filesChangedField.setAutoscrolls(false);
            filesChangedField.setEditable(false);


            JLabel jLabel = new JLabel("Revision Files");
            jLabel.setLabelFor(filesChangedField);
            ComponentWithTitlebar tbComp = new ComponentWithTitlebar();
            tbComp.setComponent(createScrollPaneTextArea(filesChangedField));
            tbComp.setLabel(jLabel);

            ResizeComponent resizablePanel = new ResizeComponent(tbComp);
            resizablePanel.setBounds(10, 10, 50, 50);

            add(resizablePanel);
        }
    }

    private ResizeComponent createTable(String label, URL url,
                                              boolean useScrollPane) {
        JTable table = new JTable();
        table.setModel(createRevisionsTable(url));
        table.setAutoCreateRowSorter(true);
        // Disable auto resizing
        //table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
//        TableColumn col = table.getColumnModel().getColumn(0);
//        int width = 80;
//        col.setPreferredWidth(width);
        
        revisionsTable = table;
        revisionsTable.addMouseListener(createRevisionsMouseLister());
        revisionsTable.addKeyListener(createRevisionsKeyLister());

        JLabel jLabel = new JLabel(label);
        jLabel.setLabelFor(table);
        ComponentWithTitlebar tbComp = new ComponentWithTitlebar();
        tbComp.setComponent(useScrollPane ? createScrollPaneTable(table) :
                            createStandaloneTable(table));
        tbComp.setLabel(jLabel);

        ResizeComponent resizablePanel = new ResizeComponent(tbComp);
        resizablePanel.setBounds(10, 10, 50, 50);

        return resizablePanel;
    }

    private JComponent createScrollPaneTable(JTable table) {
        return new JScrollPane(table);
    }

    private JComponent createScrollPaneTextArea(JTextArea textArea) {
        return new JScrollPane(textArea);
    }

    private JComponent createStandaloneTable(JTable table) {
        // Without a scrollpane, a table doesn't have its header. Let's make
        // sure we add it.
        JPanel p = new JPanel();
        p.setLayout(new BorderLayout());
        p.add(table.getTableHeader(), BorderLayout.NORTH);
        p.add(table, BorderLayout.CENTER);

        return p;
    }

    private void installAddEditRemove(ControlBar cb) {
        cb.add(createTextAction("Foo"));
        cb.add(createTextAction("Bar"));
        cb.add(createIconicAction(OracleIcons.getIcon(OracleIcons.ADD)));
        cb.add(createIconicAction(OracleIcons.getIcon(OracleIcons.EDIT)));
        cb.add(createIconicAction(OracleIcons.getIcon(OracleIcons.DELETE)));
    }

    private Action createTextAction(String text) {
        return new AbstractAction(text) {
            public void actionPerformed(ActionEvent e) {
            }
        };
    }


    private TableModel createRevisionsTable(URL url) {

        class RevisionsTableModel extends AbstractTableModel {

            NodeList revisions = null;

            RevisionsTableModel(URL url) {
                XMLExtractor extractor =
                    new XMLExtractor(url.getFile().substring(1), null);

                revisions = extractor.getNodes("revisionInfo");
            }

            public int getRowCount() {
                return revisions.getLength();
            }

            public int getColumnCount() {
                return 4;
            }

            public String getColumnName(int columnIndex) {
                switch (columnIndex) {
                case 0:
                    return "Revision";
                case 1:
                    return "Date";
                case 2:
                    return "Author";
                case 3:
                    return "Log";
                }

                return "";
            }

            public Object getValueAt(int row, int column) {
                String value = "";

                XMLElement revision = ((XMLElement)revisions.item(row));

                switch (column) {
                case 0:
                    value = revision.getAttribute("revision");
                    break;
                case 1:
                    value = revision.getAttribute("date");
                    break;
                case 2:
                    value = value = revision.getAttribute("author");
                    break;
                case 3:
                    value = value = revision.getAttribute("log");
                    break;
                }

                return value;
            }
        }

        return new RevisionsTableModel(url);
    }

    private TableModel createFilesChangedTable(URL url) {

        class FilesChangedTableModel extends AbstractTableModel {

            NodeList revisions = null;

            FilesChangedTableModel(URL url) {
                XMLExtractor extractor =
                    new XMLExtractor(url.getFile().substring(1), null);

                revisions = extractor.getNodes("revisionInfo");
            }

            public int getRowCount() {
                return revisions.getLength();
            }

            public int getColumnCount() {
                return 2;
            }

            public String getColumnName(int columnIndex) {
                switch (columnIndex) {
                case 0:
                    return "Type";
                case 1:
                    return "File";
                }

                return "";
            }

            public Object getValueAt(int row, int column) {
                String value = "";

                //                    XMLElement revision =
                //                        ((XMLElement)revisions.item(revisionsTable.getSelectedRow()));
                //
                //                    if (revision != null) {
                //                        XMLElement fileChangedNode =
                //                            (XMLElement)revision.getChildNodes().item(row);
                //
                //                        switch (column) {
                //                        case 0:
                //                            value = fileChangedNode.getAttribute("type");
                //                            break;
                //                        case 1:
                //                            value = fileChangedNode.getAttribute("path");
                //                            break;
                //                        }
                //                    }
                return value;
            }
        }

        return new FilesChangedTableModel(url);
    }

    private MouseListener createRevisionsMouseLister() {
        class RevisionsMouseListener implements MouseListener {

            public void mouseClicked(MouseEvent e) {

                XMLExtractor extractor =
                    new XMLExtractor(url.getFile().substring(1), null);

                NodeList revisions = extractor.getNodes("revisionInfo");
                XMLElement revision =
                    ((XMLElement)revisions.item(revisionsTable.getSelectedRow()));
                if (revision != null) {
                    filesChangedField.setText("");

                    String filesChanged = "";
                    NodeList changedPath =
                        revision.getElementsByTagName("changedPath");
                    for (int i = 0; i < changedPath.getLength(); i++) {

                        XMLElement changedInfo =
                            ((XMLElement)changedPath.item(i));
                        filesChanged +=
                                (i > 0 ? "\n" : "") + changedInfo.getAttribute("type") +
                                " " + changedInfo.getAttribute("path");
                    }

                    filesChangedField.setText(filesChanged);
                }
            }

            public void mousePressed(MouseEvent e) {
            }

            public void mouseReleased(MouseEvent e) {
            }

            public void mouseEntered(MouseEvent e) {
            }

            public void mouseExited(MouseEvent e) {
            }
        }

        return new RevisionsMouseListener();
    }

    private KeyListener createRevisionsKeyLister() {
        class createRevisionsKeyLister implements KeyListener {

            public void keyTyped(KeyEvent e) {
            }

            public void keyPressed(KeyEvent e) {
                XMLExtractor extractor =
                    new XMLExtractor(url.getFile().substring(1), null);

                NodeList revisions = extractor.getNodes("revisionInfo");
                XMLElement revision =
                    ((XMLElement)revisions.item(revisionsTable.getSelectedRow()));
                if (revision != null) {
                    filesChangedField.setText("");

                    String filesChanged = "";
                    NodeList changedPath =
                        revision.getElementsByTagName("changedPath");
                    for (int i = 0; i < changedPath.getLength(); i++) {

                        XMLElement changedInfo =
                            ((XMLElement)changedPath.item(i));
                        filesChanged +=
                                (i > 0 ? "\n" : "") + changedInfo.getAttribute("type") +
                                " " + changedInfo.getAttribute("path");
                    }

                    filesChangedField.setText(filesChanged);
                }
            }

            public void keyReleased(KeyEvent e) {
            }
        }

        return new createRevisionsKeyLister();
    }

}
